gsk: Tie render nodes to renderers
authorEmmanuele Bassi <ebassi@gnome.org>
Wed, 27 Jul 2016 15:23:44 +0000 (16:23 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Tue, 18 Oct 2016 10:49:10 +0000 (11:49 +0100)
Render nodes need access to rendering information like scaling factors.
If we keep render nodes separate from renderers until we submit a nodes
tree for rendering we're going to have to duplicate all that information
in a way that makes the API more complicated and fuzzier on its
semantics.

By having GskRenderer create GskRenderNode instances we can tie nodes
and renderers together; since higher layers will also have access to
the renderer instance, this does not add any burden to callers.

Additionally, if memory measurements indicate that we are spending too
much time in the allocation of new render nodes, we can now easily
implement a free-list or a renderer-specific allocator without breaking
the API.

gsk/gskrenderer.c
gsk/gskrenderer.h
gsk/gskrendernode.c
gsk/gskrendernode.h
gsk/gskrendernodeprivate.h
gtk/gtkwidget.c
gtk/gtkwindow.c

index 8a9068fe7de794d8d5a8f6032c3925f2a6b2e181..a1b9e3f217c7b73f6739e11ccf96f5da6101076c 100644 (file)
@@ -921,6 +921,7 @@ gsk_renderer_render (GskRenderer       *renderer,
   g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
   g_return_if_fail (priv->drawing_context == NULL);
   g_return_if_fail (priv->root_node == NULL);
+  g_return_if_fail (root->renderer == renderer);
 
   priv->drawing_context = g_object_ref (context);
   priv->root_node = gsk_render_node_ref (root);
@@ -1034,6 +1035,24 @@ gsk_renderer_get_use_alpha (GskRenderer *renderer)
   return priv->use_alpha;
 }
 
+/**
+ * gsk_renderer_create_render_node:
+ * @renderer: a #GskRenderer
+ *
+ * Creates a new #GskRenderNode instance tied to the given @renderer.
+ *
+ * Returns: (transfer full): the new #GskRenderNode
+ *
+ * Since: 3.22
+ */
+GskRenderNode *
+gsk_renderer_create_render_node (GskRenderer *renderer)
+{
+  g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
+
+  return gsk_render_node_new (renderer);
+}
+
 /**
  * gsk_renderer_get_for_display:
  * @display: a #GdkDisplay
index ec1d3aacc260fccda47ca5a7105d6e3ec480fed0..7928917622ca9c65dc4c340a3150577337bc557d 100644 (file)
@@ -96,6 +96,10 @@ GDK_AVAILABLE_IN_3_22
 gboolean                gsk_renderer_realize                    (GskRenderer             *renderer);
 GDK_AVAILABLE_IN_3_22
 void                    gsk_renderer_unrealize                  (GskRenderer             *renderer);
+
+GDK_AVAILABLE_IN_3_22
+GskRenderNode *         gsk_renderer_create_render_node         (GskRenderer             *renderer);
+
 GDK_AVAILABLE_IN_3_22
 void                    gsk_renderer_render                     (GskRenderer             *renderer,
                                                                  GskRenderNode           *root,
index 93bd2dda0991e11d2295be2052f37cc36f44c70c..70aeb4cc0c9ee9da23ec938fb4720d8b4d0920ac 100644 (file)
@@ -233,19 +233,22 @@ gsk_render_node_get_type (void)
   return gsk_render_node_type__volatile;
 }
 
-/**
+/*< private >
  * gsk_render_node_new:
+ * @renderer: a #GskRenderer
  *
- * Creates a new #GskRenderNode, to be used with #GskRenderer.
+ * Creates a new #GskRenderNode, to be used with #GskRenderer.
  *
  * Returns: (transfer full): the newly created #GskRenderNode
- *
- * Since: 3.22
  */
 GskRenderNode *
-gsk_render_node_new (void)
+gsk_render_node_new (GskRenderer *renderer)
 {
-  return (GskRenderNode *) g_type_create_instance (GSK_TYPE_RENDER_NODE);
+  GskRenderNode *res = (GskRenderNode *) g_type_create_instance (GSK_TYPE_RENDER_NODE);
+
+  res->renderer = renderer;
+
+  return res;
 }
 
 /**
index a4709ff453778546a03ae6f16f9b856080eb36f5..8cbd2434974bf57af2dae451ead6ab7132459491 100644 (file)
@@ -38,8 +38,6 @@ typedef struct _GskRenderNodeClass      GskRenderNodeClass;
 GDK_AVAILABLE_IN_3_22
 GType gsk_render_node_get_type (void) G_GNUC_CONST;
 
-GDK_AVAILABLE_IN_3_22
-GskRenderNode *         gsk_render_node_new                     (void);
 GDK_AVAILABLE_IN_3_22
 GskRenderNode *         gsk_render_node_ref                     (GskRenderNode *node);
 GDK_AVAILABLE_IN_3_22
index 9893f962c110e78b795f95cab1395ae7e7b55d8e..8e6bca844560f171165b853cd19cc0f8b75f568e 100644 (file)
@@ -2,6 +2,7 @@
 #define __GSK_RENDER_NODE_PRIVATE_H__
 
 #include "gskrendernode.h"
+#include "gskrenderer.h"
 #include <cairo.h>
 
 G_BEGIN_DECLS
@@ -16,6 +17,9 @@ struct _GskRenderNode
 
   volatile int ref_count;
 
+  /* Back pointer to the renderer that created the node */
+  GskRenderer *renderer;
+
   /* The graph */
   GskRenderNode *parent;
   GskRenderNode *first_child;
@@ -68,6 +72,8 @@ struct _GskRenderNodeClass
   void (* finalize) (GskRenderNode *node);
 };
 
+GskRenderNode *gsk_render_node_new (GskRenderer *renderer);
+
 void gsk_render_node_make_immutable (GskRenderNode *node);
 
 void gsk_render_node_get_bounds (GskRenderNode   *node,
index bb000e463d3b0e90911599254d329b024135f4f5..d0b3d135687a692c62b680749b8a1a787552a8f3 100644 (file)
@@ -15859,7 +15859,7 @@ gtk_widget_get_render_node (GtkWidget   *widget,
       GskRenderNode *tmp;
       cairo_t *cr;
 
-      tmp = gsk_render_node_new ();
+      tmp = gsk_renderer_create_render_node (renderer);
       gsk_render_node_set_name (tmp, "Draw Fallback");
       gsk_render_node_set_bounds (tmp, &bounds);
       gsk_render_node_set_transform (tmp, &m);
@@ -15882,7 +15882,7 @@ gtk_widget_get_render_node (GtkWidget   *widget,
           gboolean result;
           cairo_t *cr;
 
-          tmp = gsk_render_node_new ();
+          tmp = gsk_renderer_create_render_node (renderer);
           gsk_render_node_set_name (tmp, "Draw Signal Handler");
           gsk_render_node_set_bounds (tmp, &bounds);
           gsk_render_node_set_transform (tmp, &m);
index d6df84a423a275bb58e73a5111f3dc653fab61e7..786de023c51bb3bec4ce60335ae10a5b13b590b8 100644 (file)
@@ -9597,7 +9597,7 @@ gtk_window_get_render_node (GtkWidget   *widget,
   graphene_rect_init (&bounds, allocation.x, allocation.y, allocation.width, allocation.height);
   graphene_matrix_init_translate (&m, graphene_point3d_init (&p, allocation.x, allocation.y, 0.));
 
-  node = gsk_render_node_new ();
+  node = gsk_renderer_create_render_node (renderer);
   gsk_render_node_set_name (node, "Window Decoration");
   gsk_render_node_set_bounds (node, &bounds);
   gsk_render_node_set_transform (node, &m);